<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>黑白棋</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="js/moment.min.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <script src="js/socket.io/socket.io.js"></script>
    <style>
    #checker{
        width: 512px;
        height: 512px;
        border: 1px solid rgba(0, 0, 0, 0.8);
        
    }
    .grid{
        width: 62px;
        height: 62px;
        border: 1px solid rgba(0, 0, 0, 0.8);
        float: left;
    }
    .chequers{
        width: 60px;
        height: 60px;
        border: 1px solid #000;
        border-radius: 60px;
    }
    </style>


    <script>
        var log = function(s){console.log(s);}
        var socket;

        var common = {
            //单机还是联网
            isnet: true,
            //表示白棋的值
            white: 1,
            //表示黑棋的值
            black: -1,
            //没有棋子的值
            empty: 0,
            //棋盘的长
            width: 8,
            //棋盘的高
            height: 8,
            //true -> 1, false -> -1
            val: new Map([[true,1],[false,-1]]),
            //
            val2: new Map([[true,'白棋'],[false,'黑棋']]),
            //黑白棋需要遍历8个方向，定义这8个方向
            //下上左右 
            DIRECTION: [[1,0],[-1,0],   
                        [0,1],[0,-1],
                        [1,1],[-1,-1],
                        [1,-1],[-1,1]]
        }

        var core = {
            //联网时候自己的角色，false 黑棋，true 白棋,是否轮到自己下
            isme: false,
            //是否轮到白棋下
            isWhite: false,
            //表示棋盘的数组
            chequer: [0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,
                        0,0,0,1,-1,0,0,0,
                        0,0,0,-1,1,0,0,0,
                        0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0],
            //悔棋时的棋盘
            chequerClone: [],
            //悔棋时的下棋方
            isWhiteClone: [],
            //得到位置处的棋子，return: 1 白棋,-1 黑棋,0 没有棋子
            getChequer: function(x,y){
                    return this.chequer[x*common.width + y];
            },
            //立刻翻转指定位置的棋子
            setChequer: function(x,y){
                this.chequer[x*common.width + y] = common.val.get(this.isWhite);
            },
            //在x,y位置下棋，首先判断下棋的位置是否合理，然后下棋，判断对方是否无子可下，判断游戏是否结束
            play: function(x,y){
                if (common.isnet && !this.isme) {return;}
                if(this.getChequer(x,y) !== common.empty){
                    console.log(x,y,"禁着点");
                    return;
                }
                if (this.turn(x,y,false)){
                    this.chequerClone.push(this.chequer.concat());
                    this.isWhiteClone.push(this.isWhite);
                    this.setChequer(x,y);
                    if (common.isnet && this.isme) {
                        var jsonObject = {'@class': 'com.demo.dto.PositionData',
                                          x: x,
                                          y: y};
                        socket.emit("play",jsonObject);
                        this.isme = false;
                    }
                    this.turn(x,y,true);
                    this.isWhite = !this.isWhite;
                    this.draw();
                    var isPass = this.isPass();
                    if (!isPass) {
                        this.isWhite = !this.isWhite;
                        if (!this.isPass()) {
                            var [whiteNum,blackNum] = this.num();
                            if (whiteNum > blackNum) {
                                alert('白棋胜利,白子'+whiteNum+',黑子'+blackNum);
                            } else if (whiteNum < blackNum) {
                                alert('黑棋胜利,白子'+whiteNum+',黑子'+blackNum);
                            } else {
                                alert('平局');   
                            }
                            return;
                        }
                        this.isWhite = !this.isWhite;
                    }
                    if (!isPass) {
                        alert(common.val2.get(this.isWhite)+'无子可下，自动轮到'+common.val2.get(!this.isWhite)+'下');
                        this.isWhite = !this.isWhite;
                        this.isme = !this.isme;
                    }
                    return;
                }
            },
            dfplay: function(x,y){
                if(this.getChequer(x,y) !== common.empty){
                    console.log(x,y,"禁着点");
                    return;
                }
                if (this.turn(x,y,false)){
                    this.chequerClone.push(this.chequer.concat());
                    this.isWhiteClone.push(this.isWhite);
                    this.setChequer(x,y);
                    this.turn(x,y,true);
                    this.isWhite = !this.isWhite;
                    this.draw();
                    var isPass = this.isPass();
                    if (!isPass) {
                        this.isWhite = !this.isWhite;
                        if (!this.isPass()) {
                            var [whiteNum,blackNum] = this.num();
                            if (whiteNum > blackNum) {
                                alert('白棋胜利,白子'+whiteNum+',黑子'+blackNum);
                            } else if (whiteNum < blackNum) {
                                alert('黑棋胜利,白子'+whiteNum+',黑子'+blackNum);
                            } else {
                                alert('平局');   
                            }
                            return;
                        }
                        this.isWhite = !this.isWhite;
                    }
                    if (!isPass) {
                        alert(common.val2.get(this.isWhite)+'无子可下，自动轮到'+common.val2.get(!this.isWhite)+'下');
                        this.isWhite = !this.isWhite;
                        this.isme = !this.isme;
                    }
                    return;
                }
            },
            //立刻翻转棋子，往i方向赋值
            startRun: function(x, y, i){
                var turnX = x;
                var turnY = y;
                while(true){
                    turnX += common.DIRECTION[i][0];
                    turnY += common.DIRECTION[i][1];
                    if(turnX< 0 || turnX>=common.height || turnY<0 || turnY>=common.width){
                        break;
                    }
                    if(this.getChequer(turnX,turnY) == common.empty){
                        break;
                    }
                    if(common.black == this.getChequer(turnX,turnY) ^ this.isWhite){
                        break;
                    }
                    this.setChequer(turnX, turnY, this.isWhite ? common.white : common.black);
                }
            },
             //判断能否翻转棋子，isStartTurn决定是否立刻翻转棋子
            turn: function(x, y,isStartTurn){
                var isturn = false; 
                for(var i = 0; i < common.DIRECTION.length; i++){
                    var zuizhon = false;
                    var one = true;
                    var turnX = x;
                    var turnY = y;
                    while(true){
                        turnX += common.DIRECTION[i][0];
                        turnY += common.DIRECTION[i][1];
                        if(turnX< 0 || turnX>=common.height || turnY<0 || turnY>=common.width){
                            break;
                        }
                        if(this.getChequer(turnX,turnY) !== common.black && this.getChequer(turnX,turnY) !== common.white){
                            break;
                        }
                        if(this.getChequer(turnX,turnY) === common.black ^ this.isWhite){
                            if(!one){
                                zuizhon = true;
                                isturn = true;
                                break;
                            }else{
                                break;
                            }
                        }
                        one = false;
                    }
                    if(isStartTurn && zuizhon){
                        this.startRun(x,y,i);
                    }
                }
                return isturn;
            },
            //判断一方是否无子可下
            isPass: function(){
                for(var i=0; i < common.height; i++){
                    for(var j=0; j < common.width; j++){
                        if (this.getChequer(i,j) === common.empty) {
                            if (this.turn(i,j,false)){
                                return true;
                            } 
                        }
                        
                    }
                }
                return false;
            },
            //刷新棋盘
            draw: function(){
                $('#mes').text(this.isWhite?'白棋':'黑棋');
                for(var i=0; i < common.height; i++){
                    for(var j=0; j < common.width; j++){
                        if (this.getChequer(i,j) === common.white){
                            $(`#grid_${i}_${j} .chequers`).show();
                            $(`#grid_${i}_${j} .chequers`).css('background','#fff');
                            $(`#grid_${i}_${j}`).css('background','#fff');
                        } else if (this.getChequer(i,j) === common.black) {
                            $(`#grid_${i}_${j} .chequers`).show();
                            $(`#grid_${i}_${j} .chequers`).css('background','#000');
                            $(`#grid_${i}_${j}`).css('background','#fff');
                        } else {
                            $(`#grid_${i}_${j} .chequers`).hide();
                        }
                    }
                }
            },
            //返回白棋和黑棋的棋子个数
            num: function(){
                var whiteNum = 0;
                var blackeNum = 0;
                for (var i=0; i < this.chequer.length; i++){
                    if (this.chequer[i] == common.white) {
                        whiteNum++;
                    } else if (this.chequer[i] == common.black) {
                        blackeNum++;
                    }
                }
                if (whiteNum == 0) {
                    return [0, 64];
                } else if (blackeNum == 0){
                    return [64, 0];
                }
                return [whiteNum,blackeNum];
            },
            //悔棋
            retract: function(){
                if (common.isnet){
                    //TODO 联网的悔棋还未实现
                    return;
                }
                log(this.chequerClone);
                if (this.chequerClone.length > 0) {
                    this.chequer = this.chequerClone.pop();
                    this.isWhite = this.isWhiteClone.pop();
                    this.draw();
                }
            },
        }
        $(function(){
            if (common.isnet) {
                var username = 'username_' + Math.floor((Math.random()*100000)+1);
                var password = 'password_' + Math.floor((Math.random()*100000)+1);
                //使用socketio连接服务器
                socket =  io.connect('http://127.0.0.1:9092?username='+username+'&password='+password);
                
                //监听连接成功时信息
                socket.on('connect', function(data){
                    log(data);
                    if (typeof data !== 'undefined' && !data.success) {
                        alert(data.message);
                    }
                });
                
                socket.on('play', function(data, ackServerCallback) {
                    log(data);
                    core.isme = true;
                    core.dfplay(Number(data.x), Number(data.y));
                    
                    if (ackServerCallback) {
                        var jsonObject = {
                                success: true,
                                message: "confirmation",
                                code: 0};
                        ackServerCallback(jsonObject);
                    }
                });

                socket.on("message", function(data){
                    log(data);
                    $('#outMessage').text(data.message);
                });

                socket.on("gameStart",function(data){
                    log(data);
                    $('#outMessage').text(data.message);
                    core.isme = !data.white;
                    $('#mes').text(data.white?'对方':'你');
                });

                socket.on("offLine",function(data){
                    log(data)
                    $('#outMessage').text(data);
                });
            }
        });

        $(function(){
            for(var i=0; i < common.height; i++){
                for(var j=0; j < common.width; j++){
                    $('#checker').append(`<div id="grid_${i}_${j}" class="grid" x="${i}" y="${j}"><div class="chequers"></div></div>`);
                }
            }
            core.draw();
            
            //移入格子产生深色的效果
            $('.grid').hover(function(){
                var x = parseInt($(this).attr('x'));
                var y = parseInt($(this).attr('y'));
                if (0 == core.getChequer(x,y)) {
                    $(this).css('background','#aaa');
                }
            },
            function(){
                var x = parseInt($(this).attr('x'));
                var y = parseInt($(this).attr('y'));
                if (0 == core.getChequer(x,y)) {
                    $(this).css('background','#fff');
                }
            });
    
            //点击下棋
            $('.grid').click(function(){
                var x = parseInt($(this).attr('x'));
                var y = parseInt($(this).attr('y'));
                core.play(x,y);
            });
        });

        $(function(){
            

        });

        var a = -1;
        var b = -1;
    </script>
</head>
<body>
    <main>
        <div id="checker">
        </div>
        <div><span>当前轮到 </span><span id="mes">黑棋</span><span> 下</span></div>
        <div><a href="javascript:void(0);" onclick="core.retract()">悔棋</a></div>
        <div><span id="outMessage"></span></div>
    </main>
</body>
</html>